#ifndef COMMON_WIN32HANDLE_H
#define COMMON_WIN32HANDLE_H


#include "error.h"
#include <windows.h>

#include "SyncObject.h"
#include <string>
using namespace std;

namespace common { class SyncObject; } 

namespace common {

//Interface for all Win32 specjalization of synchronization objects
class Win32SyncObject {
  protected:
    //Returns windows handle to this object.
    virtual Error::code GetHandle(DWORD & handle) = 0;

};
//Handle to the Mutex object.
class Win32Mutex : public Win32SyncObject, public Mutex {
  public:
    Win32Mutex();

    Win32Mutex(const Win32Mutex & source);

    virtual ~Win32Mutex();

    Mutex & operator=(const Mutex & source);

    //Creates new mutex. If initialOwner is true, this thread will gain ownership of this mutex.
    virtual Error::code Create(bool initialOwner, string name);

    //Opens named mutex if such exists.
    virtual Error::code Open(string name);

    //Releases owned mutex.
    virtual Error::code Release();

    //Standard wait for single sync object.
    virtual Error::code WaitFor(unsigned int timeout);

    //Waits for multiple sync objects.
    virtual Error::code WaitForMultiple(unsigned int count, const SyncObject * handleList, bool waitAll, unsigned int milliseconds);

    //Closes Handle to this synchronization object and does some cleanup.
    virtual Error::code Close();


  protected:
    //Returns windows handle to this object.
    virtual Error::code GetHandle(DWORD & handle);


  private:
    //Handle to the object
    HANDLE mNativeHandle;

};
class Win32Event : public Event, public Win32SyncObject {
  public:
    Win32Event();

    Win32Event(const Win32Event & source);

    virtual ~Win32Event();

    Win32Event & operator=(const Win32Event & source);

    //Creates new event.
    //@param manualReset If true, then this object has to be set to non-signaled manualy trough Reset
    //@param initialState If true initial state is signaled.
    //@param name Name of the object
    virtual Error::code Create(bool manualReset, bool initialState, string name);

    //Opens named mutex if such exists.
    virtual Error::code Open(string name);

    //Manualy resets signaled object to non-signaled state.
    virtual Error::code Reset();

    //Changes object to signaled state.
    virtual Error::code Set();

    //Standard wait for single sync object.
    virtual Error::code WaitFor(unsigned int timeout);

    //Waits for multiple sync objects.
    virtual Error::code WaitForMultiple(unsigned int count, const SyncObject * handleList, bool waitAll, unsigned int milliseconds);

    //Closes Handle to this synchronization object and does some cleanup.
    virtual Error::code Close();


  protected:
    //Returns windows handle to this object.
    virtual Error::code GetHandle(DWORD & handle);


  private:
    //Handle to the object
    HANDLE mNativeHandle;

};
class Win32Semaphore : public Win32SyncObject, public Semaphore {
  public:
    Win32Semaphore();

    Win32Semaphore(const Win32Semaphore & source);

    virtual ~Win32Semaphore();

    Win32Semaphore & operator=(const Win32Semaphore & source);

    virtual Error::code Create(unsigned int initialCount, unsigned int maximumCount, string name);

    //Opens existing semaphore.
    virtual Error::code Open(string name);

    //Increases the count of the specified semaphore object by a specified amount.
    virtual Error::code Release(unsigned int releaseCount, unsigned int & previousCount);

    //Standard wait for single sync object.
    virtual Error::code WaitFor(unsigned int timeout);

    //Waits for multiple sync objects.
    virtual Error::code WaitForMultiple(unsigned int count, const SyncObject * handleList, bool waitAll, unsigned int milliseconds);

    //Closes Handle to this synchronization object and does some cleanup.
    virtual Error::code Close();


  protected:
    //Returns windows handle to this object.
    virtual Error::code GetHandle(DWORD & handle);


  private:
    //Handle to the object
    HANDLE mNativeHandle;

};

} // namespace common
#endif
